package top.continew.admin.controller.api;


import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.feiniaojin.gracefulresponse.api.ExcludeFromGracefulResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.continew.admin.auth.model.req.WechatGetPhoneReq;
import top.continew.admin.auth.model.req.WechatLoginReq;
import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.service.AuthService;
import top.continew.admin.common.config.properties.WxMaProperties;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.common.enums.TaskStatusEnums;
import top.continew.admin.common.service.CloudStorageService;
import top.continew.admin.common.util.ShaUtil;
import top.continew.admin.generator.model.entity.TaskAssignmentDO;
import top.continew.admin.generator.model.resp.TaskListDetailResp;
import top.continew.admin.generator.service.TaskAssignmentService;
import top.continew.admin.generator.service.TaskListService;
import top.continew.admin.system.model.req.ProcessTodoReq;
import top.continew.admin.system.model.req.TaskHandlerReq;
import top.continew.admin.system.model.req.WxMsgSubscribeReq;
import top.continew.admin.system.model.resp.ApiUserInfoResp;
import top.continew.admin.system.model.resp.MyTaskRes;
import top.continew.admin.system.model.resp.MyTaskStatisticsRes;
import top.continew.admin.system.model.resp.WxLoginResp;
import top.continew.admin.system.model.resp.user.UserDetailResp;
import top.continew.admin.system.model.resp.file.UploadResp;
import top.continew.admin.system.service.UserService;
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.web.model.R;
import top.continew.admin.generator.service.TaskTodoService;
import top.continew.admin.generator.model.resp.TaskTodoDetailResp;
import top.continew.admin.generator.model.resp.TaskTodoResp;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName ApiController
 * @Description api接口服务
 * @Author kellen
 * @Date 2025/6/25 21:35
 */
@Slf4j
@Tag(name = "应用管理 API")
@RestController
@RequiredArgsConstructor
@CrudRequestMapping(value = "/api")
public class ApiController {
    // 配置的令牌Token（需与小程序后台配置一致）
    private static final String TOKEN = "IBi4J9sXMqYPuh7JZcoMlrYu6zJ3Pm4U";

    private final AuthService authService;
    private final UserService userService;
    private final WxMaProperties wxMaProperties;

    private final TaskListService taskListService;
    private final TaskAssignmentService taskAssignmentService;
    private final CloudStorageService cloudStorageService;
    private final TaskTodoService taskTodoService;

    @SaIgnore
    @Operation(summary = "微信登录，返回token")
    @RequestMapping(value = "/wxLogin", method = RequestMethod.POST)
    public WxLoginResp wxLogin(@RequestBody WechatLoginReq req, HttpServletRequest request) {
        LoginResp login = authService.login(req, request);
        WxLoginResp wxLoginResp = new WxLoginResp();
        wxLoginResp.setToken(login.getToken());
        return wxLoginResp;
    }

    @SaIgnore
    @Operation(summary = "微信登录，返回token")
    @RequestMapping(value = "/wxMsgTokenCheck",method = {RequestMethod.POST,RequestMethod.GET})
    @ExcludeFromGracefulResponse
    public String wxLogin(@RequestParam("signature") String signature,
                               @RequestParam("timestamp") String timestamp,
                               @RequestParam("nonce") String nonce,
                               @RequestParam(value = "echostr",defaultValue = "",required = false) String echostr) {
        log.info("signature:{},timestamp:{},nonce:{},echostr:{}",signature,timestamp,nonce,echostr);
        // 1. 校验签名
        if (checkSignature(signature, timestamp, nonce)) {
            log.info("校验成功返回：echostr {}",echostr);
            // 2. 验证成功返回原始echostr
            return echostr;
        }
        // 3. 验证失败返回错误
        return "Signature verification failed";
    }

    /**
     * 微信签名校验算法
     */
    private boolean checkSignature(String signature, String timestamp, String nonce) {
        // 1. 将token、timestamp、nonce按字典序排序
        String[] arr = new String[]{TOKEN, timestamp, nonce};
        Arrays.sort(arr);

        // 2. 拼接字符串
        StringBuilder content = new StringBuilder();
        for (String s : arr) {
            content.append(s);
        }
        // 3. SHA1加密
        String encrypted = ShaUtil.sha1(content.toString());
        // 4. 与signature比对
        return encrypted != null && encrypted.equals(signature);
    }

    /**
     * 文件上传
     *
     * @param file         附件
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public UploadResp upload(@RequestPart("file") MultipartFile file) {
        String url = cloudStorageService.upload(file);
        return new UploadResp(file.getOriginalFilename(), url);
    }

    @SaIgnore
    @Operation(summary = "微信获取用户信息")
    @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
    public ApiUserInfoResp userInfo(HttpServletRequest request) {
        log.info("微信获取用户信息,token:{},用户信息：{}", StpUtil.getTokenValue(),JSON.toJSONString(UserContextHolder.getContext()));
        Long userId = UserContextHolder.getContext().getId();
        UserDetailResp userDetailResp = userService.get(userId);
        ApiUserInfoResp apiUserInfoResp = new ApiUserInfoResp();
        if (CollectionUtils.isNotEmpty(wxMaProperties.getConfigs()) && StringUtils.isNotEmpty(wxMaProperties.getConfigs().get(0).getTemplateId())) {
            List<String> ids = new ArrayList<>(Arrays.asList(wxMaProperties.getConfigs().get(0).getTemplateId().split(",")));
            apiUserInfoResp.setTemplateIds(ids);
        }
        BeanUtils.copyProperties(userDetailResp, apiUserInfoResp);
        return apiUserInfoResp;
    }

    @Operation(summary = "微信获取手机号")
    @RequestMapping(value = "/wxPhone", method = RequestMethod.POST)
    public WxLoginResp wxPhone(@RequestBody WechatGetPhoneReq req, HttpServletRequest request) {
        log.info("获取微信手机号,token:{} params:{}", StpUtil.getTokenValue(), JSON.toJSONString(req));
        WxLoginResp login = authService.wxPhone(req, request);
        WxLoginResp wxLoginResp = new WxLoginResp();
        wxLoginResp.setToken(login.getToken());
        return wxLoginResp;
    }

    @Operation(summary = "微信消息订阅")
    @RequestMapping(value = "/wxMsgSubscribe", method = RequestMethod.POST)
    public R wxMsgSubscribe(@RequestBody WxMsgSubscribeReq wxMsgSubscribeReq, HttpServletRequest request) {
        log.info("微信消息订阅,token:{},用户信息：{}", StpUtil.getTokenValue(),JSON.toJSONString(UserContextHolder.getContext()));
        userService.wxMsgSubscribe(wxMsgSubscribeReq);
        return R.ok();
    }

    @Operation(summary = "首页统计个人任务信息")
    @RequestMapping(value = "/statistics", method = RequestMethod.GET)
    public R<MyTaskStatisticsRes> statistics() {
        log.info("首页统计个人任务信息,token:{}", StpUtil.getTokenValue());
        //MyTaskStatisticsRes statisticsRes = MyTaskStatisticsRes.builder().waitProcess(0).theSameMonth(0).todayProcessed(0).accumulatedProcessed(0).build();
        MyTaskStatisticsRes statisticsRes=taskListService.statistics();
        return R.<MyTaskStatisticsRes>ok(statisticsRes);
    }

    @Operation(summary = "任务列表页面")
    @RequestMapping(value = "/taskPage", method = RequestMethod.GET)
    public PageResp<MyTaskRes> taskList(@RequestParam("type") String type,
                                        @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
                                        @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                        @RequestParam(value = "shopName", required = false) String shopName,
                                        @RequestParam(value = "categoryName", required = false) String categoryName) {
        log.info("任务列表页面,token:{} type:{},pageSize:{},pageNum：{},shopName:{},categoryName:{}", StpUtil.getTokenValue(),type,pageSize,pageNum,shopName,categoryName);
        return taskListService.queryByType(type,pageSize,pageNum,shopName,categoryName);
    }

    @Operation(summary = "任务明细")
    @RequestMapping(value = "/task/{id}", method = RequestMethod.GET)
    public R<MyTaskRes> taskOne(@PathVariable("id")Long id) {
        TaskListDetailResp taskListDetailResp = taskListService.get(id);
        if(taskListDetailResp==null){
            return null;
        }
        List<TaskAssignmentDO> tas = taskAssignmentService.list(new LambdaQueryWrapper<TaskAssignmentDO>().eq(TaskAssignmentDO::getTaskId, taskListDetailResp.getId()));
        if(CollectionUtils.isNotEmpty(tas)){
            Long userId = UserContextHolder.getUserId();
            List<TaskAssignmentDO> list = tas.stream().filter(t -> t.getHandlerId().equals(userId) && null == t.getViewTime()).toList();
            if(CollectionUtils.isNotEmpty(list)){
                list.forEach(t->{
                    t.setViewTime(LocalDateTime.now());
                    t.setStatus(TaskStatusEnums.UN_DO.getValue());
                });
                taskAssignmentService.updateBatchById(list);
            }
        }
        MyTaskRes myTaskRes = new MyTaskRes();
        BeanUtils.copyProperties(taskListDetailResp,myTaskRes);
        // 填充处理图片信息
        String handlePicUrl = taskListDetailResp.getHandlePicUrl();
        if(StringUtils.isNotEmpty(handlePicUrl)){
            myTaskRes.setImages(Arrays.stream(handlePicUrl.split(",")).toList());
        }
        log.info("任务明细,token:{} 任务id{},返回：{}", StpUtil.getTokenValue(),id,JSON.toJSONString(myTaskRes));
        return R.ok(myTaskRes);
    }

    @Operation(summary = "消息处理")
    @RequestMapping(value = "/taskHandler", method = RequestMethod.POST)
    public R taskHandler(@RequestBody TaskHandlerReq taskHandlerReq) {
        // 业务逻辑校验：如果选择完成，必须上传附件；如果选择转派，可以不上传附件
        if ("done".equals(taskHandlerReq.getTaskStatus()) && (taskHandlerReq.getFiles() == null || taskHandlerReq.getFiles().isEmpty())) {
            return R.fail(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()),"完成任务时必须上传至少一张图片");
        }
        
        taskListService.taskHandler(taskHandlerReq);
        log.info("消息处理,token:{} 参数{}", StpUtil.getTokenValue(),JSON.toJSONString(taskHandlerReq));
        return R.ok("处理成功");
    }

    @Operation(summary = "获取我的待办事项统计")
    @RequestMapping(value = "/myTodoStats", method = RequestMethod.GET)
    public R<Map<String, Object>> getMyTodoStats() {
        Long userId = UserContextHolder.getUserId();
        Map<String, Object> taskTodoStats = taskTodoService.getTaskTodoStats(userId);
        log.info("消息处理,token:{} 返回：{}", StpUtil.getTokenValue(),JSON.toJSONString(taskTodoStats));
        return R.ok(taskTodoStats);
    }

    @Operation(summary = "获取我的待办事项列表")
    @RequestMapping(value = "/myTodoList", method = RequestMethod.GET)
    public R<PageResp<TaskTodoResp>> getMyTodoList(@RequestParam(defaultValue = "1") Integer page,
                                                   @RequestParam(defaultValue = "10") Integer size,
                                                   @RequestParam(required = false) String status) {
        Long userId = UserContextHolder.getUserId();
        List<Integer> statusInt=new ArrayList<>();
        if(StringUtils.isNotBlank(status)){
            statusInt=Arrays.stream(status.split(",")).toList().stream().map(Integer::valueOf).collect(Collectors.toList());
        }
        return R.ok(taskTodoService.getMyTodoList(userId, page, size, statusInt));
    }

    @Operation(summary = "获取待办事项详情")
    @RequestMapping(value = "/todoDetail/{id}", method = RequestMethod.GET)
    public R<TaskTodoDetailResp> getTodoDetail(@PathVariable Long id) {
        return R.ok(taskTodoService.getTodoDetail(id));
    }

    @Operation(summary = "处理待办事项")
    @RequestMapping(value = "/processTodo", method = RequestMethod.POST)
    public R processTodo(@RequestBody ProcessTodoReq req) {
        taskTodoService.processTodo(req);
        return R.ok();
    }

    @Operation(summary = "获取任务转派记录")
    @GetMapping("/{taskId}/transfers")
    public R<Object> getTaskTransfers(@PathVariable Long taskId) {
        return R.ok(taskListService.getTransferChain(taskId));
    }

}